package com.zrx.app.android.UTIL;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.location.Location;
import android.location.LocationManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.github.hiteshsondhi88.libffmpeg.FFmpeg;
import com.github.hiteshsondhi88.libffmpeg.FFmpegExecuteResponseHandler;
import com.github.hiteshsondhi88.libffmpeg.LoadBinaryResponseHandler;
import com.github.hiteshsondhi88.libffmpeg.exceptions.FFmpegNotSupportedException;
import com.zrx.app.android.ZRXApplication;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;

import static android.content.Context.TELEPHONY_SERVICE;

/**
 * Created by liuji on 2017/4/14.
 */

public class ZRXUTIL {
    public static final String TAG = "ZRXUTIL";
    public static final int REQ_TAKE_PHOTO = 0;
    public static final int REQ_LOCAL_PHOTO = 1;
    public static final int REQ_TAKE_VIDEO = 2;
    public static final int REQ_LOCAL_VIDEO = 3;
    public static final int MY_PERMISSIONS_REQUEST_READ_CONTACTS = 66;

    public static String path = ZRXApplication.getAppContext().getExternalFilesDir(null) + "/ZRX";
    static BitmapFactory.Options options = new BitmapFactory.Options();
    static FFmpeg ffmpeg = FFmpeg.getInstance(ZRXApplication.getAppContext());

    static {
        options.inSampleSize = calculateInSampleSize(options, 2000, 2828);
        options.inJustDecodeBounds = false;
    }

    static {
        try {
            ffmpeg.loadBinary(new LoadBinaryResponseHandler() {

                @Override
                public void onStart() {
                }

                @Override
                public void onFailure() {
                }

                @Override
                public void onSuccess() {
                }

                @Override
                public void onFinish() {
                }
            });
        } catch (FFmpegNotSupportedException e) {
            // Handle if FFmpeg is not supported by device
        }
    }

    public static String getPath() {
        return path;
    }

    public static String getCachePath() {
        return path + "/cache";
    }

    public static JSONObject getRecordJson(String id) {
        String str = getStringFromFile(path + "/" + id + "/obj.json");
        return JSON.parseObject(str);
    }

    public static String getStringFromFile(String path) {
        try {
            FileInputStream fis = new FileInputStream(path);
            Scanner sc = new Scanner(fis);
            StringBuilder sb = new StringBuilder();
            int count;
            while (sc.hasNextLine()) {
                sb.append(sc.nextLine());
                sb.append("\n");
            }
            sc.close();
            return sb.toString();
        } catch (Exception e) {

        }
        return null;
    }

    public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {
            final int heightRatio = Math.round((float) height / (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }
        return inSampleSize;
    }

    public static void compressImg(String src, String out) {
        try {
            Bitmap bitmap = BitmapFactory.decodeFile(src, options);
            FileOutputStream os = new FileOutputStream(out);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 60, os);
        } catch (Exception e) {
            Log.d("UTIL", e.getMessage());
        }
    }

    public static void compressImg(Bitmap srcBitmap, String out) {
        try {
            FileOutputStream os = new FileOutputStream(out);
            srcBitmap.compress(Bitmap.CompressFormat.JPEG, 60, os);
        } catch (Exception e) {
            Log.d("UTIL", e.getMessage());
        }
    }

    public static String getPhotoFile(String id, String key) {
        return path + "/" + id + "/" + key + ".jpg";
    }

    public static String getRawPhotoFile(String id, String key) {
        return path + "/" + id + "/" + key + ".raw.jpg";
    }

    public static String getVideoFile(String id, String key) {
        return path + "/" + id + "/" + key + ".mp4";
    }

    public static String getRawVideoFile(String id, String key) {
        return path + "/" + id + "/" + key + ".raw.mp4";
    }

    public static FFmpeg getFfmpeg() {
        return ffmpeg;
    }

    public static JSONObject loadState(String id) {
        File file = new File(path + "/" + id + "/obj.json");
        if (!file.exists())
            return null;
        try {
            Scanner sc = new Scanner(file);
            StringBuilder sb = new StringBuilder();
            while (sc.hasNextLine())
                sb.append(sc.nextLine());
            JSONObject re = JSON.parseObject(sb.toString(), Feature.OrderedField);
            sc.close();
            return re;

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void saveState(JSONObject rootObj) {
        saveState(rootObj, false);
    }

    public static void saveState(JSONObject rootObj, boolean force) {
        String id = rootObj.getJSONObject("rawRecord").getString("id");
        String recordState = "";
        if (rootObj.containsKey("state"))
            recordState = rootObj.getString("state");
        if (("submitting".equals(recordState) || "uploading".equals(recordState) || "done".equals(recordState) || "retry".equals(recordState) || "error".equals(recordState)) && force == false) {
            Log.i(TAG, "record is in " + recordState + " state. use force=ture to save the case");
            return;
        }

        File file = new File(path + "/" + id + "/obj.json");
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(file);
            fos.write(rootObj.toJSONString().getBytes());
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static String translateState(String state) {
        switch (state) {
            case "UPLOADING":
                return "等待录入资料";
            case "EXAMING":
                return "内部审核中";
            case "EXAM_PASS":
                return "内部审核-通过";
            case "EXAM_FAIL":
                return "内部审核-未通过";
            case "EXAM_SENDBACK":
                return "内部审核-退回";
            case "EXT_EXAM_PASS":
                return "等待录入放款资料";
            case "EXT_EXAM_FAIL":
                return "外部审核-未通过";
            case "EXT_EXAM_SENDBACK":
                return "外部审核-退回";
            case "GPS_INSTALLING":
                return "GPS安装&放车";
            case "FAIL":
                return "未通过/异常";
            case "INSTALL_SENDBACK":
                return "电核-退回";
            case "DONE":
                return "完成（结案）";
            case "CREDIT_AUDIT_PASS":
                return "人审通过";
            case "CREDIT_AUDIT_FAIL":
                return "人审未通过";
            case "TARCUSTOM":
                return "车审通过";
            case "LOAN_EXAMING":
                return "放款内审中";
            case "LOAN_EXAM_SENDBACK":
                return "放款资料退回";
            case "LOAN_RECEIPT_CONFIRM_SENDBACK":
                return "车商收据退回";
            case "LOAN_PAYMENT_OUT_CONFIRM_PASS":
                return "等待录入车商收据";
            case "CAR_DONE": return "放车完成";

            case "CAR_EXAMING":
                return "放车内审中";
            case "CAR_EXAM_SENDBACK":
                return "放车内审退回";
            case "CAR_EXAM_FAIL":
                return "放车内审拒绝";
            case "CAR_EXAM_PASS":
                return "放车内审通过";
            case "CAR_EXPERT_EXAM_PASS":
                return "放车车审通过";
            case "CAR_EXPERT_EXAM_SENDBACK":
                return "放车车审退回";
            case "CAR_EXPERT_EXAM_FAIL":
                return "放车车审拒绝";
            case "CAR_FINAL_EXAM_FAIL":
                return "放车最终确认拒绝";
            case "CAR_FINAL_EXAM_SENDBACK":
                return "放车最终确认退回";
            case "LOAN_DONE":
                return "放款完成";

            default:
                return state;
        }
    }

    public static int translateStateToColor(String state) {
        switch (state) {
            case "UPLOADING":
                return Color.rgb(150, 145, 141);
            case "EXAMING":
                return Color.rgb(173, 212, 227);
            case "EXAM_PASS":
                return Color.rgb(140, 205, 190);
            case "EXAM_FAIL":
                return Color.rgb(239, 142, 146);
            case "EXAM_SENDBACK":
                return Color.rgb(214, 178, 152);
            case "EXT_EXAM_PASS":
                return Color.rgb(140, 205, 190);
            case "EXT_EXAM_FAIL":
                return Color.rgb(239, 142, 146);
            case "EXT_EXAM_SENDBACK":
                return Color.rgb(214, 178, 152);
            case "GPS_INSTALLING":
                return Color.rgb(140, 205, 190);
            case "FAIL":
                return Color.rgb(239, 142, 146);
            case "INSTALL_SENDBACK":
                return Color.rgb(214, 178, 152);
            case "DONE":
                return Color.rgb(140, 205, 190);
            case "CREDIT_AUDIT_PASS":
                return Color.rgb(133, 192, 186);
            case "CREDIT_AUDIT_FAIL":
                return Color.rgb(239, 142, 146);
            case "TARCUSTOM":
                return Color.rgb(133, 192, 186);
            case "LOAN_EXAM_SENDBACK":
                return Color.rgb(214, 178, 152);
            case "LOAN_RECEIPT_CONFIRM_SENDBACK":
                return Color.rgb(214, 178, 152);
            case "LOAN_PAYMENT_OUT_CONFIRM_PASS":
                return Color.rgb(150, 145, 141);
            case "CAR_EXAMING":
                return  Color.rgb(237, 199, 85);
            case "CAR_EXAM_SENDBACK":
                return Color.rgb(214, 178, 152);
            case "CAR_EXAM_FAIL":
                return Color.rgb(239, 142, 146);
            case "CAR_EXAM_PASS":
                return Color.rgb(133, 192, 186);
            case "CAR_EXPERT_EXAM_PASS":
                return Color.rgb(133, 192, 186);
            case "CAR_EXPERT_EXAM_SENDBACK":
                return Color.rgb(214, 178, 152);
            case "CAR_EXPERT_EXAM_FAIL":
                return Color.rgb(239, 142, 146);
            case "CAR_FINAL_EXAM_SENDBACK":
                return Color.rgb(214, 178, 152);
            case "LOAN_DONE":
                return Color.rgb(140, 205, 190);
            default:
                return Color.argb(128, 128, 128, 128);
        }
    }


    public static void compressVideo(String src, String tar, FFmpegExecuteResponseHandler handler) {
        if (handler == null)
            handler = new DefaultFFmpegExecuteResponseHandler();
        Log.d("video", "ffmpeg start");
        //.\ffmpeg.exe -i temp.mp4 -vcodec libx264 -preset medium -crf 35 -y -vf "scale=1920:-1" -acodec libmp3lame -an a.mp4
        //String []cmd={/*"-vcodec libx264",*/"-preset medium","-crf 35","-y","-vf \"scale=1920:-1\"","-acodec libmp3lame","-i "+src,tar};
        //String []cmd={"-version"};
        String[] cmd = {"-i", src, "-vcodec", "libx264", "-preset", "medium", "-crf", "35", "-y", "-acodec", "libmp3lame", tar};
        try {
            getFfmpeg().execute(cmd, handler);
        } catch (Exception e) {
            Log.d("video ffmpeg Exception", e.getMessage());
        }

        //Log.d("video","ffmpeg end");
    }

    public static void copyFile(InputStream inStream, FileOutputStream fs) {
        try {
            int bytesum = 0;
            int byteread = 0;
            byte[] buffer = new byte[1444];
            int length;
            while ((byteread = inStream.read(buffer)) != -1) {
                bytesum += byteread; //字节数 文件大小
                System.out.println(bytesum);
                fs.write(buffer, 0, byteread);
            }
            inStream.close();
        } catch (Exception e) {
            e.printStackTrace();

        }

    }

    public static List<String> sortByOrder(Set<String> keySet, final JSONObject json) {
        List<String> orderList = new ArrayList<String>(keySet);

        Collections.sort(orderList, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                int order1 = 0, order2 = 0;
                if (json.get(o1) instanceof Map && json.getJSONObject(o1).containsKey("order"))
                    order1 = json.getJSONObject(o1).getInteger("order");

                if (json.get(o2) instanceof Map && json.getJSONObject(o2).containsKey("order"))
                    order2 = json.getJSONObject(o2).getInteger("order");

                if (order1 == order2)
                    return o1.compareTo(o2);
                return order1 - order2;
            }
        });
        return orderList;
    }

    public static void fillData(JSONObject data) {
        JSONObject template = data.getJSONObject("template");
        JSONObject raw = data.getJSONObject("raw");
        JSONObject basicData = raw.getJSONObject("basicData");
        JSONObject paymentInfo = raw.getJSONObject("paymentInfo");
        JSONObject attachments = raw.getJSONObject("attachments");
        JSONObject addtionalData = raw.getJSONObject("addtionalData");
        String id = raw.getString("id");
        template.put("id", id);

        String rawState = "";
        if (raw != null && raw.containsKey("state"))
            rawState = raw.getString("state");
        String recordState = "";
        if (data.containsKey("state"))
            recordState = data.getString("state");

        if ("EXAM_SENDBACK".equals(rawState) && "done".equals(recordState)) {
            data.put("editable", true);
            data.remove("state");
        }

        Map<String, Object> allTarNode = new HashMap<>();
        for (String key : template.keySet()) {
            Object _ele = template.get(key);
            if (_ele != null && _ele instanceof JSONObject) {
                JSONObject l2 = (JSONObject) _ele;
                Set<String> l2KeySet = l2.keySet();
                for (String l2Key : l2KeySet) {
                    Object obj = l2.get(l2Key);
                    if (obj != null && obj instanceof JSONObject)
                        allTarNode.put(l2Key, obj);
                }
            }
        }
        //allTarNode.remove("order");
        Map<String, Object> allSrcNode = new HashMap<>();
        if (basicData != null)
            allSrcNode.putAll(basicData);
        if (paymentInfo != null)
            allSrcNode.putAll(paymentInfo);
        if (addtionalData != null)
            allSrcNode.putAll(addtionalData);
        if (attachments != null)
            allSrcNode.putAll(attachments);


        JSONObject other = template.getJSONObject("参考资料");

        if (allSrcNode != null)
            for (String srcKey : allSrcNode.keySet()) {
                try {
                    String srcVal = (String) allSrcNode.get(srcKey);
                    boolean flag = false;
                    boolean editable = true;

                    for (String tarKey : allTarNode.keySet()) {
                        JSONObject tar = (JSONObject) allTarNode.get(tarKey);
                        boolean appendable = false;
                        if (tar.containsKey("appendable")) {
                            appendable = tar.getBoolean("appendable");
                        }

                        if (tar.containsKey("editable")) {
                            editable = tar.getBoolean("editable");
                        }

                        if (tarKey != null && tarKey.equals(srcKey)) {
                            updateEle(tar, srcKey, srcVal, id, editable);
                            flag = true;
                        } else if (srcKey != null && tarKey != null && appendable && srcKey.contains(tarKey)) {
                            JSONObject innerNode = tar.getJSONObject("val");
                            if (innerNode == null) {
                                innerNode = new JSONObject();
                                tar.put("val", innerNode);
                            }
                            //innerNode.put(srcKey,val);
                            JSONObject _tar = null;
                            if (innerNode.containsKey(srcKey))
                                _tar = innerNode.getJSONObject(srcKey);
                            else {
                                _tar = new JSONObject();
                                innerNode.put(srcKey, _tar);
                            }
                            _tar.put("type", tar.getString("type"));

                            updateEle(_tar, srcKey, srcVal, id, editable);
                            flag = true;
                        } else if (tar.containsKey("alias")) {
                            JSONArray arrKey = tar.getJSONArray("alias");
                            for (Object aliasKey : arrKey) {
                                if (aliasKey != null && aliasKey.equals(srcKey)) {
                                    updateEle(tar, srcKey, srcVal, id, editable);
                                    flag = true;
                                    break;
                                }
                            }
                        }
                        if (flag)
                            break;
                    }
                    if (!flag) {

                        JSONObject _node = new JSONObject();
                        if (srcKey.contains("照片"))
                            _node.put("type", "照片");
                        else if (srcKey.contains("视频"))
                            _node.put("type", "视频");
                        else
                            _node.put("type", "字段");
//                        if (false == editable)
                        _node.put("editable", false);
                        //_node.put("order", other.size());
                        _node.put("val", srcVal);
                        other.put(srcKey, _node);

                    }
                } catch (Exception e) {
                    Log.d(TAG, e.getMessage());
                }

            }


    }

    public static void updateEle(JSONObject tar, String key, String val, String id, boolean editable) {
        String tarType = tar.getString("type");
        if (tar.containsKey("val") && !"".equals(tar.get("val"))) {
            String tarVal = tar.getString("val");
            if (tarType.equals("字段")) {
                tar.put("rawVal", val);
            } else if (tarType.equals("照片") && tarVal != null && !tarVal.equals(val)) {
                new File(ZRXUTIL.getPhotoFile(id, key)).delete();
                new File(ZRXUTIL.getRawPhotoFile(id, key)).delete();
                tar.put("val", val);
            } else if (tarType.equals("视频") && tarVal != null && !tarVal.equals(val)) {
                new File(ZRXUTIL.getVideoFile(id, key)).delete();
                new File(ZRXUTIL.getRawVideoFile(id, key)).delete();
                tar.put("val", val);
            }
        } else
            tar.put("val", val);
        tar.put("editable", editable);
    }


    static class DefaultFFmpegExecuteResponseHandler implements FFmpegExecuteResponseHandler {
        @Override
        public void onStart() {

        }

        @Override
        public void onFinish() {

        }

        @Override
        public void onSuccess(String message) {
            Log.d("video ffmpeg onSuccess", message);
        }

        @Override
        public void onProgress(String message) {
            Log.d("video ffmpeg onProgress", message);
        }

        @Override
        public void onFailure(String message) {
            Log.d("video ffmpeg onFailure", message);
        }
    }


    public static String getIMEI() {
        try {
            String imei = ((TelephonyManager) ZRXApplication.getAppContext().getSystemService(TELEPHONY_SERVICE))
                    .getDeviceId();
            //Log.d(TAG, "IMEI:" + Imei);
            return imei;
        } catch (Exception e) {
            return null;
        }
    }

    public static void requestLocationPermission(Activity activity){
        if (ContextCompat.checkSelfPermission(ZRXApplication.getAppContext(),
                Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {


            ActivityCompat.requestPermissions(activity,
                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                    MY_PERMISSIONS_REQUEST_READ_CONTACTS);


        }
    }

    public static Location getLocation() {

        LocationManager locationManager = (LocationManager) ZRXApplication.getAppContext().getSystemService(Context.LOCATION_SERVICE);
        //获取所有可用的位置提供器
        List<String> providers = locationManager.getProviders(true);
        Location location =null;
        if (providers.contains(LocationManager.GPS_PROVIDER)) {
            try{
                location =locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            }catch (SecurityException e){
                Log.d(TAG,e.getMessage());
            }
        }
        if (providers.contains(LocationManager.NETWORK_PROVIDER)&&location==null) {
            try{
                location =locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
            }catch (SecurityException e){
                Log.d(TAG,e.getMessage());
            }
        }

        return location;
    }
}
